-- 2022-8-18

---[[ 20.2 关系运算相关的元方法

    -- 元表还允许我们指定关系运算符的含义 其中的元方法包括对于(__eq) 小于(__lt)和小于等于(__le)
    -- 其他三个关系运算符没有单独的元方法 Lua语言会将a~=b转换为not(a==b) a>b转换为b<a a>=b转换为b <= a

    -- 在Lua语言的老版本中 Lua语言会通过将a<=b转换为not(b<a)来把所有的关系运算符转化为一个关系运算符
    -- 不过 这种转化在遇到部分有序(partial order)时就会不正确 所谓部分有序是指 并非所有类型的元素都能够被正确地排序
    -- 例如 由于Not a Number(NaN)的存在 大多数计算机中的浮点数就不是完全可以排序的
    -- 根据IEEE 754标准 NaN代表未定义的值 例如 0/0的结果就是NaN
    -- 标准规定任何涉及NaN的比较都应返回假 这就意味着NaN <= x 永远为假 x<NaN也为假
    -- 因此 在这种情况下 a<=b到not(b<a)的转化也就不合法了

    -- 在集合的示例中 我们也面临类似的问题 <=显而易见且有用的含义是集合包含:a<=b通常意味着a是b的一个子集
    -- 然而 根据部分有序的定义 a<=b和b<a可能同时为假
    -- 因此 我们就必须实现__le(小于等于 子集关系)和__lt(小于 真子集关系):
    mt,__le = function (a,b) -- 子集
        for k in pairs(a) do
            if not b[k] then
                return false
            end
        end
        return true
    end
    mt,__lt = function (a,b) -- 真子集
        return a <= b and not (b <= a)
    end
    -- 最后 我们还可以通过集合包含来定义集合相等
    mt,__eq = function (a,b)
        return a <= b and b <= a
    end
    -- 有了这些定义后 我们就可以比较集合了:
    s1 = Set.new{2,4}
    s2 = Set.new{4,10,2}
    print(s1<=s2)
    print(s1<s2)
    print(s1>=s2)
    print(s1>s2)
    print(s1==s2*s1)

    -- 相等比较有一些限制 如果两个对象的类型不同 那么相等比较操作不会调用任何元方法而直接返回false 因此 不管元方法如何 集合永远不等于数字
--]]